#include "dswax_msg_client.h"

static const ST_P2PMSG_T m_axmsg[] = {
	{"MSG_PUA_REGIST_V2", NULL, CDswax_msg_client::cbOnPUARegistV2},
	{"MSG_GET_PARAM_MODIFY_V2_RESP", "MSG_GET_PARAM_V2_REQ", CDswax_msg_client::cbOnGetParamModifyV2},
	{"MSG_GET_PARAM_V2_RESP", "MSG_GET_PTZSET_V2_REQ", CDswax_msg_client::cbOnGetParamV2},
	{"MSG_GET_PTZSET_V2_RESP", NULL, CDswax_msg_client::cbOnGetPTZSetV2},
	{"MSG_SET_PARAM_V2_RESP", NULL, NULL},

	{"END", NULL, NULL},
};

CDswax_msg_client::CDswax_msg_client(LPST_ENV_T pEnv, char * pHost, int nPort, CB_AX_MSG_CLIENT pCBFunc, void* pCaller, char* pDevID)
: CDswtcpclient_base(pEnv, pHost, nPort)
, m_pCBFunc(pCBFunc)
, m_pCaller(pCaller)
, m_bNeedReconnect(true)
, m_bValid(true)
{
	LOG4CPLUS_DEBUG(log_dsw, "Create CDswax_msg_client class! id = " << pDevID);
	strcpy(m_sDevID, pDevID);
	m_nTask_Monitor.ev = m_nTask_CmdMonitor.ev = NULL;
	SendMessage(PMSG_GET_DEVICE_BASE_PARAM, &m_nBaseParam);
	m_sCurParamTM[0] = '\0';
}

CDswax_msg_client::~CDswax_msg_client()
{
	CLEAR_EV(m_nTask_Monitor);
	CLEAR_EV(m_nTask_CmdMonitor);
	LOG4CPLUS_DEBUG(log_dsw, "Destroy CDswax_msg_client class! id = " << m_sDevID);
}

int CDswax_msg_client::MakePayloadLength(char* pData, int nLen)
{
	return *((int*)pData);
}

void CDswax_msg_client::DestroyClient()
{
	m_bNeedReconnect = false;
	m_bValid = false;
	bufferevent_disable(m_pBev, EV_READ | EV_WRITE);
	bufferevent_setcb(m_pBev, NULL, NULL, NULL, this);
	delete this;
}

void CDswax_msg_client::PostDestroyClient()
{
	m_bNeedReconnect = false;
	m_bValid = false;
}

void CDswax_msg_client::OnError(struct bufferevent *bev, short events)
{
	CLEAR_EV(m_nTask_Monitor);
	CLEAR_EV(m_nTask_CmdMonitor);
	if (m_pCBFunc && !m_bNeedReconnect)
		m_pCBFunc(PMSG_AX_CLIENT_ERROR, m_sDevID, NULL, m_pCaller);
	else if (m_pCBFunc){
		char sURL[512];
		m_pCBFunc(PMSG_AX_CLIENT_ERROR, m_sDevID, sURL, m_pCaller);
		char sIP[64], sMsgPort[64], sAVPort[64];
		if (sscanf(sURL, "%*[IP:]%[0-9.]%*[,AV:]%[0-9]%*[,MG:]%[0-9],", sIP, sAVPort, sMsgPort) == 3){
			if ((strcmp(sIP, m_sHost) != 0) || (atoi(sMsgPort) != m_nPort)){
				strcpy(m_sHost, sIP);
				m_nPort = atoi(sMsgPort);
			}
		}
	}
	if (m_bNeedReconnect){
		m_bValid = true;
		m_sCurParamTM[0] = '\0';
		ReConnect(1, 0);
	}
	else
		delete this;
}

void CDswax_msg_client::OnConnect(struct bufferevent *bev, short events)
{
	m_bNeedReconnect = true;
	m_nWantReadLen = sizeof(int);
	CDswtcpclient_base::OnConnect(bev, events);
}

bool CDswax_msg_client::ProcessMessage(char* pMsg, int nLen, struct evbuffer *outbuf)
{
	if (!m_bValid)
		return false;

	CMarkup xml;
	char sMsgReq[64] = {0};
	char sCallID[64] = {0};
	char* pCallID = sCallID;

	xml.SetDoc(pMsg);
	if(!xml.FindElem("Message"))
		return false;
	if (strlen(xml.GetAttrib("MsgType").c_str()) > 0){
		strcpy(sCallID, xml.GetAttrib("CID").c_str());
		strcpy(sMsgReq, xml.GetAttrib("MsgType").c_str());
	}
	else{
		xml.IntoElem();
			if (!xml.FindElem("DSW_HEADER"))
				return false;
			xml.IntoElem();
				if (!xml.FindElem("MessageType"))
					return false;
				strcpy(sMsgReq, xml.GetData().c_str());
				pCallID = NULL;
			xml.OutOfElem();
		xml.OutOfElem();
	}
	LPST_P2PMSG_T pPos = (LPST_P2PMSG_T)m_axmsg;
	bool bRet = false;
	while(strcmp(pPos->sMsgReq, "END") != 0){
		if (strcmp(pPos->sMsgReq, sMsgReq) == 0){
			if (pPos->pP2PFunc != NULL)
				bRet = pPos->pP2PFunc(pCallID, pMsg, pPos->sMsgIDResp, this);
			else
				bRet = true;
			break;
		}
		pPos ++;
	}
	if (bRet){
		if (m_nTask_Monitor.ev){
			TRIG_EV(m_nTask_Monitor, 10, 0);
		}
		else{
			CREATE_EV(m_nTask_Monitor, 1, 0, m_pEnv->pEvBase, CDswax_msg_client::cbMonitorTask, this);
		}
	}
	return bRet;
}

void CDswax_msg_client::SendMsg(char * pMsg)
{
	int nSendLen = strlen(pMsg);
	if (nSendLen > 0){
		evbuffer_add(bufferevent_get_output(m_pBev), &nSendLen, sizeof(int));
		evbuffer_add(bufferevent_get_output(m_pBev), pMsg, nSendLen);
	}
}

void CDswax_msg_client::MonitorTask(int fd, short events)
{
	CMarkup xml;
	char sBuf[64];
	sprintf(sBuf, "%s_%d", m_nBaseParam.devid, time(NULL));
	MAKEMSGHEAD_V2(xml, sBuf, "MSG_GET_PARAM_MODIFY_V2_REQ");
	SendMsg((char*)xml.GetDoc().c_str());
}

void CDswax_msg_client::MonitorCmdTask(int fd, short events)
{
	CMarkup xml;
	char sBuf[64];
	if (m_pCBFunc){
		m_pCBFunc(PMSG_AX_GETCMD, m_sDevID, &xml, m_pCaller);
		if (strlen(xml.GetDoc().c_str()) > 0)
			SendMsg((char*)xml.GetDoc().c_str());
	}
	TRIG_EV(m_nTask_CmdMonitor, 0, 1000 * 100);
}

bool CDswax_msg_client::OnPUARegistV2(char* pCId, void* pMsgReq, const char* pMsgIDResp)
{
	CMarkup xml;
	xml.SetDoc((char*)pMsgReq);
	if (!xml.FindElem("Message"))
		return false;
	xml.IntoElem();
	if (!xml.FindElem("DSW_RESULT"))
		return false;
	xml.IntoElem();
	if (!xml.FindElem("DSW_DEV"))
		return false;
	if (strcmp(m_sDevID, xml.GetAttrib("PUAID").c_str()) != 0)
		return false;
	
	if (m_nTask_CmdMonitor.ev){
		TRIG_EV(m_nTask_CmdMonitor, 0, 1000 * 100);
	}
	else{
		CREATE_EV(m_nTask_CmdMonitor, 0, 1000 * 100, m_pEnv->pEvBase, CDswax_msg_client::cbMonitorCmdTask, this);
	}
	return true;
}

bool CDswax_msg_client::OnGetParamModifyV2(char* pCId, void* pMsgReq, const char* pMsgIDResp)
{
	CMarkup xml;
	char sBuf[64];
	char sMakeTM[32] = {0};
	xml.SetDoc((char*)pMsgReq);
	if (!xml.FindElem("Message"))
		return false;
	xml.IntoElem();
	if (!xml.FindElem("DSW_RESULT"))
		return false;
	xml.IntoElem();
	if (!xml.FindElem("MODIFY"))
		return false;
	strcpy(sMakeTM, xml.GetAttrib("MAKETIME").c_str());
	if (strcmp(sMakeTM, m_sCurParamTM) != 0){
		strcpy(m_sCurParamTM, sMakeTM);
		sprintf(sBuf, "%s_%d", m_nBaseParam.devid, time(NULL));
		MAKEMSGHEAD_V2(xml, sBuf, pMsgIDResp);
		SendMsg((char*)xml.GetDoc().c_str());
	}
	return true;
}

bool CDswax_msg_client::OnGetParamV2(char* pCId, void* pMsgReq, const char* pMsgIDResp)
{
	CMarkup xml;
	char sBuf[64] = {0};
//printf("sss = %s\n", (char*)pMsgReq);
	xml.SetDoc((char*)pMsgReq);
	if (!xml.FindElem("Message"))
		return false;
	xml.IntoElem();
	if (!xml.FindElem("DSW_RESULT"))
		return false;
	xml.IntoElem();
	if (!xml.FindElem("Message"))
		return false;
	xml.IntoElem();
	while(xml.FindElem()){
		if (strcmp(xml.GetTagName().c_str(), "MEDIA") == 0){
			xml.IntoElem();
			if (!xml.FindElem("VIDEO"))
				return false;
			xml.IntoElem();
			while(xml.FindElem("SUB_STREAM")){
				int nStreamID = atoi(xml.GetAttrib("RESOLUTION").c_str());
				if (nStreamID == SUB_STREAM){
					if (m_pCBFunc){
						ST_AX_DIM_FPS_T nDimFps;
						memcpy(&nDimFps.nDIM, &defRESOLUTIONS_X03[nStreamID], sizeof(gm_dim_t));
						nDimFps.nFps = atoi(xml.GetAttrib("FPS").c_str());
						m_pCBFunc(PMSG_SET_EXTCAM_DIM_FPS, m_sDevID, (void*)&nDimFps, m_pCaller);
					}
					break;
				}
			}
			xml.OutOfElem();
			xml.OutOfElem();
		}
		else if (strcmp(xml.GetTagName().c_str(), "SYSTEM") == 0){
			xml.IntoElem();
			if (xml.FindElem("PTZSET")){
				ST_PTZ_X03_POS_T nCurPos;
				nCurPos.xPos = atoi(xml.GetAttrib("X").c_str());
				nCurPos.yPos = atoi(xml.GetAttrib("Y").c_str());
				if (m_pCBFunc)
					m_pCBFunc(PMSG_SET_EXTCAM_CURPOS, m_sDevID, (void*)&nCurPos, m_pCaller);
			}
			xml.OutOfElem();
		}
	}
	return true;
}

bool CDswax_msg_client::OnGetPTZSetV2(char* pCId, void* pMsgReq, const char* pMsgIDResp)
{
	CMarkup xml;

	xml.SetDoc((char*)pMsgReq);
	if (!xml.FindElem("Message"))
		return false;
	xml.IntoElem();
	if (!xml.FindElem("DSW_RESULT"))
		return false;
	xml.IntoElem();
	if (xml.FindElem("PTZSET")){
		ST_PTZ_X03_POS_T nCurPos;
		nCurPos.xPos = atoi(xml.GetAttrib("X").c_str());
		nCurPos.yPos = atoi(xml.GetAttrib("Y").c_str());
		if (m_pCBFunc)
			m_pCBFunc(PMSG_SET_EXTCAM_CURPOS, m_sDevID, (void*)&nCurPos, m_pCaller);
	}
	return true;
}


